/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright (c) 2008-2009, The KiWi Project (http://www.kiwi-project.eu)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * - Redistributions of source code must retain the above copyright notice, 
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution.
 * - Neither the name of the KiWi Project nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Contributor(s):
 * 
 * 
 */
package kiwi.core.model.rdf;

import kiwi.core.model.Constants;
import kiwi.core.model.annotations.RDF;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Index;

import javax.persistence.*;
import java.io.Serializable;

/**
 * KiWiResources correspond to RDF resources. A KiWi resource is either an anonymous 
 * resource or a URIResource. A KiWiResource represents an RDF resource. However, there
 * is no 1:1 correspondance, as there may be several KiWiResources in different
 * KnowledgeSpaces that represent the same RDF resource.
 * <p>
 * Each KiWiResource has a 1:1 correspondance to a content item. Each KiWiResource is 
 * also directly related with a Sesame 2 resource in the knowledge base backend. 
 * The kiwi.sesame package contains appropriate adaptors for transforming Sesame 2 
 * resources into KiWiResources.
 * <p>
 * 
 * Each KiWiResoure furthermore participates in exactly one knowledge space, where the RDF 
 * resource may have different identifiers for the users. This knowledge space defines the 
 * getTripleStore().of the node. For this reason, a Sesame 2 Value may correspond to several
 * KiWiNodes in different knowledge spaces.
 * <p>
 * TODO: we could further simplify the data model by treating TextContent and MediaContent
 * as literals that are in a certain relation with the resource ("kiwi:hasTextContent",
 * "kiwi:hasMediaContent") and introducing the following new literal types:
 * KiWiTextContentLiteral
 * KiWiMediaContentLiteral
 * KiWiStringContentLiteral
 *
 * The class hierarchy should be changed so that from KiWiNode -> KiWiLiteral and from
 * KiWiNode -> KiWiResource there is joined subclass, and from there on single table
 *
 * currently existing functionality should be moved to ContentItemService
 *
 * @author Sebastian Schaffert
 */

@SuppressWarnings({"JpaQlInspection"})
@Entity
@DiscriminatorValue("RESOURCE")
//@SecondaryTable( name = "KIWIRESOURCE")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@BatchSize(size = 100)
//@org.hibernate.annotations.Table(appliesTo="KIWIRESOURCE", optional=false)
@NamedQueries({
        @NamedQuery(name  = "tripleStore.resourceByUri",
                query = "from KiWiUriResource r " +
                        "where r.uri = :uri " +
                        "  and r.deleted = false"),
        @NamedQuery(name  = "tripleStore.resourceByAnonId",
                query = "from KiWiAnonResource r " +
                        "where r.anonId = :anonId " +
                        "  and r.deleted = false "),
        @NamedQuery(name  = "tripleStore.subjectByProperty",
                query = "select t.subject " +
                        "from KiWiTriple t " +
                        "where t.property.uri = :prop_uri" +
                        "  and t.subject.deleted = false" +
                        "  and (t.deleted = false)"),
        @NamedQuery(name  = "tripleStore.subjectByPropertyValue",
                query = "select t.subject " +
                        "from KiWiTriple t " +
                        "where t.property.uri = :prop_uri" +
                        "  and t.object = :value" +
                        "  and t.subject.deleted = false" +
                        "  and (t.deleted = false)"),
        @NamedQuery(name  = "tripleStore.subjectByPropertyLiteralValue",
                query = "select t.subject " +
                        "from KiWiTriple t " +
                        "where t.property.uri = :prop_uri" +
                        "  and t.object.content = :value" +
                        "  and t.subject.deleted = false" +
                        "  and (t.deleted = false)"),
        @NamedQuery(name="contentItemService.bySpace",
                query="select ci from KiWiResource ci " +
                        "where ci.context = :space " +
                        "  and ci.deleted = false"),
        @NamedQuery(name="contentItemService.bySpaceType",
                query="select t.subject from KiWiTriple t " +
                        "where t.property.uri = '"+Constants.NS_RDF+"type' " +
                        "  and t.object = :type " +
                        "  and t.deleted = false " +
                        "  and t.subject.deleted = false " +
                        "  and t.subject.context = :space " +
                        "order by t.subject.title"),

    // TODO: check whether these are still needed!
    @NamedQuery(name="contentItemService.byUriIncludeDeleted",
    		    query="from KiWiUriResource ci " +
    		          "where ci.uri = :uri"),
     @NamedQuery(name="contentItemService.byTitle",
    		    query="from KiWiResource ci " +
    		    	  "where ci.title = :title and ci.deleted = false"),
    @NamedQuery(name="contentItemService.byId",
			    query="from KiWiResource ci " +
			    	  "where ci.id = :id"),
    @NamedQuery(name="contentItemService.list",
    		    query="from KiWiResource ci " +
    		    	  "where ci.deleted = false"),
    @NamedQuery(name="contentItemService.count",
			    query="select count(ci.id) " +
			    	  "from KiWiResource ci " +
			    	  "where ci.deleted = false"),
    @NamedQuery(name="contentItemService.listSorted", // predictable sort order
			    query="from KiWiResource ci " +
			    	  "where ci.deleted = false " +
			    	  "order by ci.id"),
    @NamedQuery(name="commentService.listTextContent",
                query="select content " +
                      "from KiWiTextContentLiteral content, KiWiTriple t " +
                      "where t.deleted = false " +
                      "and t.object.id = content.id " +
                      "and t.property.uri = '"+Constants.NS_KIWI_CORE+"hasTextContent' " +
                      "and t.subject = :item " +
                      "order by t.created desc"),
    @NamedQuery(name="commentService.listMediaContent",
                query="select content " +
                      "from KiWiTextContentLiteral content, KiWiTriple t " +
                      "where t.deleted = false " +
                      "and t.object.id = content.id " +
                      "and t.property.uri = '"+Constants.NS_KIWI_CORE+"hasMediaContent' " +
                      "and t.subject = :item " +
                      "order by t.created desc"),
    @NamedQuery(name="commentService.listComments",
			    query="select comment " +
			    	  "from KiWiResource comment, KiWiTriple t " +
			    	  "where comment.deleted = false " +
			    	  "and t.object.id = comment.id " +
			    	  "and t.property.uri = '"+Constants.NS_KIWI_CORE+"hasComment' " +
			    	  "and t.subject = :item " +
			    	  "order by t.created desc"),
    @NamedQuery(name="contentItemService.listByDate",
			    query="select ci "+
			          "from KiWiResource ci " +
			    	  "where " +
			    	  "  NOT EXISTS (from KiWiTriple t " +
			    	  "              where ci.id = t.subject.id " +
			    	  "                and t.property.uri = '"+Constants.NS_RDF+"type' " +
			    	  "                and t.object.uri in ('"+Constants.NS_KIWI_CORE+"Tagging')) " +
			    	  "  and ci.deleted = false " +
			    	  "order by ci.created desc"),
	/* retrieve a content item by its type; type is a KiWiResource object passed as named parameter ":type" */
	@NamedQuery(name="kiwiEntityManager.ciTitleByUri",
			    query="select ci.title " +
				      "from KiWiUriResource ci " +
			    	  "where ci.uri = :uri and ci.deleted = false"),
	@NamedQuery(name="kiwiGATEService.listContentItems", /* efficient listing of URI and title */
			    query="select ci.title, ci.uri " +
				      "from KiWiUriResource ci " +
	  				  "where ci.deleted=false"),
	@NamedQuery(name="kiwiEntityManager.queryContentItem",
				query="from KiWiUriResource o " +
			    	  "where o.uri    IN (:uris)"),
	@NamedQuery(name="contentItemService.byAuthor",
			    query="from KiWiResource ci " +
			    	  "where ci.creator.login = :login and ci.deleted = false"),
	@NamedQuery(name="contentItemService.currentVersionId",
			    query="select ci.version from KiWiResource ci " +
					  "where ci.id = :id ")
})
public abstract class KiWiResource extends KiWiNode implements Serializable {
    
	private static final long serialVersionUID = 1L;


    @Transient
    private String namespacePrefixCache;



    /** the title of the contentitem **/
//    @NotNull
    @Index(name="idx_content_item_title")
    @RDF(Constants.NS_KIWI_CORE+"title")
    @Column(length = 255)
//    @Column(table = "KIWIRESOURCE", length = 255)
    private String title;

    protected KiWiResource() {
        super();
    }


     /**
     * Return the localised title of this content item. Currently, the title is represented by the
     * RDF label of the corresponding resource; the method thus just delegates to KiWiResource.getLabel(Locale).
     * @return
     */
    public String getTitle() {
        return title;
    }

    /**
     * Set the localised title of this content item. Currently, the title is represented by the
     * RDF label of the corresponding resource; the method thus just delegates to KiWiResource.setLabel(Locale,String).
     * @param title
     */
    public void setTitle(String title) {
        this.title = title;
    }





    @Override
    public abstract boolean isAnonymousResource();

    @Override
    public boolean isLiteral() {
        return false;
    }

    @Override
    public abstract boolean isUriResource();


    public abstract String getKiwiIdentifier();

    /**
     * Return a unique cache key for this Content Item
     *
     * @author
     * @return
     * @see KiWiNode#getCacheKey()
     */
    @Override
    public abstract String getCacheKey();

}
